package nr.nodehost.model;

import java.io.File;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.nfunk.jep.JEP;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Service;

@Data
@Service
@Slf4j
public class Schema {
    public static final int IDLE = 0;
    public static final int PENDING = 1;
    public static final int DEPLOYING = 2;
    public static final int RUNNING = 3;
    public static final int COMPLETED = 4;

    private int id;
    private String name;
    private String description;
    //    private int loopNumber;
    private String createDate;
    private String modifyDate;
    private String stopDate;    //任务的自动停止时间，任务部署时候选择是否加上该字段
    private String userId;
    private JSONObject content;
    private int status;
    private int progress;
    private String info;
    private int categoryId;
    private int step;
    //    private boolean compiled;
    private JSONArray params;
    private int dataSourceSize;    //数据源发送帧的大小，单位Bytes
    private int listenPort;     //  dataAccess组件的listenPort，由webserver分配并显示在前端，run的时候分配
    private String result_uuid;    //	结果组件的UUID
    private HashMap<String, JSONObject> components = new HashMap<String, JSONObject>();
    private ArrayList<JSONObject> links = new ArrayList<JSONObject>();
    //private ArrayList<JSONObject> params=new ArrayList<JSONObject>();

    // Add by hengGuo
    // component id -> node ip
    private HashMap<String, String> componentnodemap = new HashMap<String, String>();
    private JSONObject scheduleLimit;    //调度限制，json格式，AsyncTaskService.java526行，schemaJson中有之前没有的scheduleLimit
    private JSONObject scheduleResult;   //调度结果

    public Schema() {

    }

    public void preprocess() {
//		JSONObject content=JSONObject.fromObject(getContent());
        JSONArray cells = content.getJSONArray("cells");
        for (Object o : cells) {
            JSONObject cell = (JSONObject) o;
            if (cell.getString("type").equalsIgnoreCase("devs.Model")) {
                // Modified by hengGuo
//				components.put(cell.getString("id"), cell);
                String id = cell.getString("id");
                components.put(id, cell);

                //  Add by hengGuo
                JSONObject resourceParam = cell.getJSONObject("componentParam").getJSONObject("resourceParam");
                if (resourceParam != null) {
//                    componentnodemap.put(id, resourceParam.getString("node")); todo
                    System.out.println("---resourceParam="+resourceParam);
                    componentnodemap.put(id, resourceParam.getString("nodeIp"));
                }
            } else if (cell.getString("type").equalsIgnoreCase("link")) {
                links.add(cell);
            }
        }

        for (JSONObject comp : components.values()) {
            log.info(String.valueOf(comp.getJSONArray("outPorts")));
            if (comp.getJSONArray("outPorts").size() == 0) {
                this.result_uuid = comp.getString("id");
                log.info(result_uuid);
            }
        }
    }


    public HashMap<String, JSONObject> getComponents() {
        return components;
    }


    public JSONObject getPortSourceComponent(String componentUuid, String portName) {
        JSONObject sourceComponent = null;
        for (JSONObject link : links) {
            JSONObject target = link.getJSONObject("target");
            if (target.getString("id").equals(componentUuid) && target.getString("port").equals(portName)) {
                JSONObject source = link.getJSONObject("source");
                sourceComponent = components.get(source.getString("id"));
            }
        }
        return sourceComponent;
    }

    public List<JSONObject> getPortTargetComponents(String componentUuid, String portName) {
        ArrayList<JSONObject> targetComponents = new ArrayList<JSONObject>();
        for (JSONObject link : links) {
            JSONObject source = link.getJSONObject("source");
            if (source.getString("id").equals(componentUuid) && source.getString("port").equals(portName)) {
                JSONObject target = link.getJSONObject("target");
                targetComponents.add(components.get(target.getString("id")));
            }
        }
        return targetComponents;
    }

    public String getTargetPortName(String sourceComponentId, String sourceComportPort, String targetComponentId) {
        for (JSONObject link : links) {
            JSONObject source = link.getJSONObject("source");
            JSONObject target = link.getJSONObject("target");
            if (source.getString("id").equals(sourceComponentId) && source.getString("port").equals(sourceComportPort) && target.getString("id").equals(targetComponentId)) {
                return target.getString("port");
            }
        }
        return null;
    }

    public double evaluateParamExpression(String expression) {
        double result = 0;
        try {

            JEP jep = new JEP();

            for (int i = 0; i < params.size(); i++) {
                JSONObject globalParam = params.getJSONObject(i);
                System.out.format("name:%s value:%f factor:%f\n", globalParam.getString("name"), globalParam.getDouble("value"), globalParam.getDouble("unitFactor"));
                jep.addVariable(globalParam.getString("name"), globalParam.getDouble("value") * globalParam.getDouble("unitFactor"));
            }
            jep.parseExpression(expression);
            result = jep.getValue();
            System.out.format("%s=%f\n", expression, result);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }
}
